/* css操作 */
const less = require('less');
const sass = require('sass');
const stylus = require('stylus');
const Fs = require('@lib/utils/fs');
const {
  isValuableArray
} = require('@lib/utils/tools');

class Css {
  /**
   * 查找样式主文件（一般是index.xxx 或者 main.xxx）
   * @param {*} list 样式文件列表
   * @returns 样式主文件列表，一般只有一个
   */
  static findMainFiles(list) {
    return list.filter(item => item.fileName.indexOf('index') > -1 || item.fileName.indexOf('main') > -1) || [];
  }

  /**
   * 单个less文件内容转化成css
   * @param {*} lessFilePath less文件路径
   * @returns css内容
   */
  static async singleLess2Css(lessFilePath) {
    const content = Fs.readFileSync(lessFilePath);
    try {
      const output = await less.render(content, { filename: lessFilePath });
      return output.css;
    } catch (error) {
      console.error(`Error converting LESS to CSS: ${error}`);
      return null;
    }
  }

  /**
   * 单个sass文件内容转化成css
   * @param {*} sassFilePath sass文件路径
   * @returns css内容
   */
  static async singleSass2Css(sassFilePath) {
    try {
      const output = await sass.compileAsync(sassFilePath);
      return output.css;
    } catch (error) {
      console.error(`Error converting SASS to CSS: ${error}`);
      return null;
    }
  }

  /**
   * 单个stylus文件内容转化成css
   * @param {*} stylusFilePath stylus文件路径
   * @returns css内容
   */
  static async singleStylus2Css(stylusFilePath) {
    const content = Fs.readFileSync(stylusFilePath);
    try {
      const output = await stylus.render(content, { filename: stylusFilePath });
      return output;
    } catch (error) {
      console.error(`Error converting STYLUS to CSS: ${error}`);
      return null;
    }
  }

  /**
   * less列表文件转化成css
   * @param {*} lessList less文件列表
   * @returns 拼接好的css内容
   */
  static async less2Css(lessList) {
    // 1.先找到主样式文件
    const mainList = Css.findMainFiles(lessList);
    let ret = '';
    // 2.存在则读取主样式文件即可
    if (isValuableArray(mainList)) {
      for (const item of mainList) {
        const { filePath } = item;
        const cssContent = await Css.singleLess2Css(filePath);
        if (cssContent) {
          ret += cssContent;
        }
      }
      return ret;
    }
    // 没有主样式文件则遍历全部less文件
    for (const item of lessList) {
      const { filePath } = item;
      const cssContent = await Css.singleLess2Css(filePath);
      if (cssContent) {
        ret += cssContent;
      }
    }
    return ret;
  }

  /**
   * sass列表文件转化成css
   * @param {*} sassList sass文件列表
   * @returns 拼接好的css内容
   */
  static async sass2Css(sassList) {
    // 1.先找到主样式文件
    const mainList = Css.findMainFiles(sassList);
    let ret = '';
    // 2.存在则读取主样式文件即可
    if (isValuableArray(mainList)) {
      for (const item of mainList) {
        const { filePath } = item;
        const cssContent = await Css.singleSass2Css(filePath);
        if (cssContent) {
          ret += cssContent;
        }
      }
      return ret;
    }
    // 没有主样式文件则遍历全部sass文件
    for (const item of sassList) {
      const { filePath } = item;
      const cssContent = await Css.singleSass2Css(filePath);
      if (cssContent) {
        ret += cssContent;
      }
    }
    return ret;
  }

  /**
   * stylus列表文件转化成css
   * @param {*} stylusList stylus文件列表
   * @returns 拼接好的css内容
   */
  static async stylus2Css(stylusList) {
    // 1.先找到主样式文件
    const mainList = Css.findMainFiles(stylusList);
    let ret = '';
    // 2.存在则读取主样式文件即可
    if (isValuableArray(mainList)) {
      for (const item of mainList) {
        const { filePath } = item;
        const cssContent = await Css.singleStylus2Css(filePath);
        if (cssContent) {
          ret += cssContent;
        }
      }
      return ret;
    }
    // 没有主样式文件则遍历全部stylus文件
    for (const item of stylusList) {
      const { filePath } = item;
      const cssContent = await Css.singleStylus2Css(filePath);
      if (cssContent) {
        ret += cssContent;
      }
    }
    return ret;
  }

  /**
   * 判断给定的css样式节点是否使用了nth-child伪类
   * @param {*} styleNode 样式节点
   * @returns 是否使用了nth-child伪类-布尔值
   */
  static hasNthChild(styleNode) {
    const selector = styleNode.selectors && styleNode.selectors[0];
    return selector && selector.includes(':nth-child');
  }

  /**
   * 判断给定的css样式节点是否使用了position: fixed属性
   * @param {*} styleNode 样式节点
   * @returns 是否使用了position: fixed属性-布尔值
   */
  static hasFixedPosition(styleNode) {
    return (
      styleNode &&
      styleNode.declarations &&
      styleNode.declarations.some(
        (decl) =>
          decl.property && decl.property.toLowerCase().trim() === 'position' && decl.value.toLowerCase().trim() === 'fixed'
      )
    );
  }
}

module.exports = Css;
